

const Round =qguan(0,"Round")
const Block =qguan(0,"Block")
const Row =qguan(0,"Row")
const Dar =qguan(0,"Dar")
const PubSub =qguan(0,"PubSub")
const Trans =qguan(0,"Trans")
const Save =qguan(0,"Save")
const OutPut =qguan(0,"OutPut")
const Execute =qguan(0,"Execute")

/**
 * 中心
 *
 *  默认绑定 事件
 *      0 保存
 *      1 输入 字符串或Round 转换成 语法树
 *      2 输出 字符串或Round
 */

export  default  class Qexe{

    constructor(){
        this.dar=new Dar();
        this.stack={};
        this.heap=new Dar();
        this.pubSub=new PubSub();
       // this.arrayQueue =new ArrayQueue();
        this.pubSub.on("0",this._null.bind(this));
        this.pubSub.on("1",this._save.bind(this));
        this.pubSub.on("2",this._trans.bind(this));
        this.pubSub.on("3",this._outPut.bind(this))
        this.trans=new Trans(this);
    }



    /**
     *  参数都是 buff
     * @param dataRow
     * @param dataBlock
     * @param linkRow
     */
    loadData(data ){
       // this.init();
        this.dar.loadData(data)
        //导入之后，需要判断一下，1里面有没有数据，如果没有添加一下
        /*    let  square=   this.dar.findData(1,0,null,null);
            if(!square){
                this.dar.addData(1,null,null,new Block()) // 虚 块 添加 square
            }*/
    }

    outData(){
        let buff=this.dar.outData();
        return  buff;
    }

    saveDataHub(dataHub){
        this.dataHub=dataHub;
    }
    /**
     * 初始化
     */
    init(){
        this.dar=new Dar();
        // this.addRound(); //目录 可能也不需要、 、
        // 字初始化
        this.dar.addData(null,null,null,new Round()) //实  块
        this.dar.addData(null,null,null,new Round()) //虚  块
        this.dar.addData(1,null,null,new Block()) // 虚 块 添加 square

    }
    run(a,b,c,d){

        let execute=new Execute(this);

        execute.run(a,b,c,d)

    }

    /**
     *
     * @param key
     * @param obj
     * @param caller    回调
     * @param callfun  处理过程
     */
    on(key,obj,caller,callfun){

        if(callfun){
            this.pubSub.on(key,callfun);
        }else {
            let aa=`  function(a,b,c,d) {
                let obj=qguan("`+ obj+`");
                let trans=new obj(this);
                let res=  trans.run(a,b,c,d)
                 if(!res){
                       return 
                    }
                if(d){
                    if(res instanceof Array){
                          this.emit(d,...res)
                    }else{
                         this.emit(d,res)
                    }
                 
                }else{
                 if(res instanceof Array){
                       this.emit('`+caller+`',...res)
                    }else{
                        this.emit('`+caller+`',res)
                    }
                }
           } `
            let obs =eval(aa);
            this.pubSub.on(key,this.obs.bind(this));
        }


    }

    emit(eventType, ...args){
        this.pubSub.emit(eventType,...args);
    }

    /**
     * 设置 文字 和文件的输出 接口
     * @param data
     */
    start(data){


    }

    _trans(a,b,c,d) {
        let trans=new Trans(this);
        let res=  trans.run(b,c,d)
        if(!res){
           return
        }
        if(d){
            if(res instanceof Array){
                this.emit(d,...res)
            }else{
                this.emit(d,res)
            }

        }else{
            if(res instanceof Array){
                this.emit('1',...res)
            }else{
                this.emit('1',res)
            }
        }
    }

    _save(a,b,c,d) {
        let save=new Save(this);
        let res= save.run(b,c,d)

        if(!res){
            return
        }
        if(d){
            if(res instanceof Array){
                this.emit(d,...res)
            }else{
                this.emit(d,res)
            }

        }else{
            if(res instanceof Array){
                this.emit('3',...res)
            }else{
                this.emit('3',res)
            }
        }
    }
    _outPut(a,b,c,d) {
        let outPut =new OutPut(this);
        let res= outPut.run(b,c,d)
        if(!res){
            return
        }

        if(d){
            if(res instanceof Array){
                this.emit(d,...res)
            }else{
                this.emit(d,res)
            }

        }else{
            if(res instanceof Array){
                this.emit('0',...res)
            }else{
                this.emit('0',res)
            }
        }
    }

    _null(a,b,c,d) {

    }


    /**
     *
     * @param row
     * @param func
     * @param resType
     * @returns {*}
     */
    findReal(row,realId,func,resType){
        if(realId!=null&&typeof(realId) != "undefined"){
            this.realId=realId;
            return this.dar.findData(0,null,null,this.realDefaultFunc.bind(this))
        }
        if(resType){
            this.resRealType=resType;
        }else {
            this.resRealType='real';
        }
        if(row){
            this.realRow=row;
        }else {
            this.realRow=new Row(null,null,null,null);
        }
        if(func){
            return this.dar.findData(1,0,null,func)
        }
        return this.dar.findData(0,null,null,this.realDefaultFunc.bind(this))
    }
    realByIdFunc(roundId,BlockId,RowId,dataThis){
        let   realId=this.realId;
        return dataThis.list[realId];
    }

    realDefaultFunc(roundId,BlockId,RowId,dataThis){
        let word=this.realRow;
        let realId= this.realId;
        if(realId!=null){
            this.realId=null;
            return  dataThis.list[realId];
        }
        for(let n=0;n<dataThis.list.length;n++){
            let square=  dataThis.list[n];
            for(let l=0;l<square.list.length;l++){
                let row=square.list[l];
                let res=[];
                if(row.isValue(1,word.find(1))){
                    res.push(1)
                }
                if(row.isValue(2,word.find(2))){
                    res.push(2)
                }
                if(row.isValue(3,word.find(3)) ){
                    res.push(3)
                }
                if(row.isValue(4,word.find(4))){
                    res.push(4)
                }
                if(res.length==4){
                    if(this.resRealType=='real') {
                        return square;
                    }
                    return l;
                }
            }
        }
        return null;

    }
}


